﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine.Networking;
using UnityEngine.Scripting;

namespace ZyGame.Avatar
{
    public class RequestCreateFileData
    {
        public string sid;
        public string name;
        public string md5;
        public int size;
        public string type;
        public string audit_status;

        [Preserve]
        public RequestCreateFileData()
        {
        }

        [Preserve]
        public RequestCreateFileData(string name, string md5, string type, string status, int size)
        {
            this.sid = "1";
            this.name = name;
            this.size = size;
            this.type = type;
            this.audit_status = status;
            this.md5 = md5;
        }
    }

    public class Matter
    {
        public string id;
        public string sid;
        public string md5;
        public string name;
        public string type;
        public int size;
        public string audit_status;
        public string @object;
        public string url;

        [Preserve]
        public Matter()
        {
        }
    }

    public class Data
    {
        public int code;
        public string msg;
        public Matter matter;
        public Dictionary<string, List<string>> headers;
        public string up_link;

        [Preserve]
        public Data()
        {
        }
    }

    public class ResponseCreateFile
    {
        public int code;
        public string msg;
        public Data data;

        public UploadAssetResponse Generic()
        {
            return new UploadAssetResponse()
            {
                code = 200,
                msg = string.Empty,
                data = new UploadData()
                {
                    name = data.matter.name,
                    sid = data.matter.sid,
                    md5 = data.matter.md5,
                    type = data.matter.type,
                    url = data.matter.url,
                    size = data.matter.size,
                }
            };
        }

        [Preserve]
        public ResponseCreateFile()
        {
        }
    }

    public class UploadData
    {
        public string id;
        public string sid;
        public string md5;
        public string name;
        public string type;
        public int size;
        public string audit_status;
        public string @object;
        public string url;
        [Preserve]
        public UploadData()
        {
        }
    }

    public class UploadAssetResponse
    {
        public int code;
        public string msg;
        public UploadData data;
        [Preserve]
        public UploadAssetResponse()
        {
        }
    }

    public class CreateElementData
    {
        public int id;
        [Preserve]
        public CreateElementData()
        {
        }
    }

    public class CreateElementResponse
    {
        public int code;
        public string msg;
        public Data data;
        [Preserve]
        public CreateElementResponse()
        {
        }
    }

    public class ServerElementData
    {
        public string id;
        public int element;
        public int organization_id;
        public string name;
        public string icon;
        public string icon_hash;
        public int publish_status;
        public int price;
        public string model;
        public string texture;
        public string model_name;
        [Preserve]
        public ServerElementData()
        {
        }
    }

    public class ElementDataList
    {
        public List<ServerElementData> list;
        public int max_count;
        [Preserve]
        public ElementDataList()
        {
        }
    }

    public class ResponsePublishingElementDatas
    {
        public int code;
        public string msg;
        public ElementDataList data;
        [Preserve]
        public ResponsePublishingElementDatas()
        {
        }
    }
    internal static class AvatarExtension
    {
        public static void SetRequestHeaders(this UnityWebRequest request, Dictionary<string, List<string>> headers)
        {
            if (request == null || headers == null || headers.Count <= 0)
            {
                return;
            }

            if (headers != null && headers.Count > 0)
            {
                foreach (var item in headers)
                {
                    for (int i = 0; i < item.Value.Count; i++)
                    {
                        request.SetRequestHeader(item.Key, item.Value[i]);
                    }
                }
            }
        }
        public static IEnumerator UploadAsset(RequestCreateFileData requestCreate, byte[] bytes, Action<UploadAssetResponse, Exception> callback)
        {
            string postData = Newtonsoft.Json.JsonConvert.SerializeObject(requestCreate);
            byte[] bodyRaw = Encoding.UTF8.GetBytes(postData);
            using UnityWebRequest request = UnityWebRequest.Post(AvatarSetting.address + "avatar/resource/v1/matter/create", postData);
            Client.Console.WriteLineFormat("{0} {1}", request.url, postData);
            request.uploadHandler = new UploadHandlerRaw(bodyRaw);
            request.SetRequestHeader("Content-Type", "application/json");
            request.SetRequestHeader("userid", AvatarSetting.user);
            request.SetRequestHeader("pid", AvatarSetting.pid.ToString());
            yield return request.SendWebRequest();
            if (!request.isDone || request.result != UnityWebRequest.Result.Success)
            {
                callback(null, new Exception(request.error + "\n" + request.downloadHandler.text));
                yield break;
            }
            Client.Console.WriteLine(request.downloadHandler.text);
            ResponseCreateFile responseCreateFile = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseCreateFile>(request.downloadHandler.text);
            if (responseCreateFile.code != 200)
            {
                callback(null, new Exception(responseCreateFile.msg));
                yield break;
            }
            if (string.IsNullOrEmpty(responseCreateFile.data.up_link))
            {
                callback(responseCreateFile.Generic(), null);
                yield break;
            }

            using var request1 = UnityWebRequest.Put(responseCreateFile.data.up_link, bytes);
            request1.SetRequestHeaders(responseCreateFile.data.headers);
            yield return request1.SendWebRequest();
            if (!request1.isDone || request1.result != UnityWebRequest.Result.Success)
            {
                callback(null, new Exception(request1.error + "\n" + request1.downloadHandler.text));
                yield break;
            }

            using var request2 = UnityWebRequest.Post(AvatarSetting.address + "avatar/resource/v1/matter/done?name=" + requestCreate.name, string.Empty);
            request2.SetRequestHeader("userid", AvatarSetting.user);
            request2.SetRequestHeader("pid", AvatarSetting.pid.ToString());
            yield return request2.SendWebRequest();
            if (!request2.isDone || request2.result != UnityWebRequest.Result.Success)
            {
                callback(null, new Exception(string.Format("{0}\n{1}\n{2}", request2.url, request2.error, request2.downloadHandler.text)));
            }
            else
            {
                Client.Console.WriteLine(request2.downloadHandler.text);
                UploadAssetResponse response = Newtonsoft.Json.JsonConvert.DeserializeObject<UploadAssetResponse>(request2.downloadHandler.text);
                if (response.code != 200)
                {
                    callback(null, new Exception(response.msg));
                }
                else
                {
                    callback(response, null);
                }
            }
        }

    }
}
